/**
 * @copyright Copyright (c) 2022 OnMicro Corp.
 * @brief     The function address and its symbol name, derived from ELF.
 * @author    wei.lu@onmicro.com.cn
 * @license   SPDX-License-Identifier: Apache-2.0
 */
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vpi_user.h>

typedef struct sym_pair_s {
  uint32_t address;
  char name[16];
} sym_pair_t;
static sym_pair_t *m_symbol_table;
static int m_symbol_entries;

bool elf_load_file(char *filename)
{
  FILE *fp;
  int lines = 0;
  sym_pair_t *sym_tbl;

  if (NULL != m_symbol_table) return true;

  fp = fopen(filename, "r");
  if (NULL == fp) {
    return false;
  }

  while (!feof(fp)) {
    int ch = fgetc(fp);
    if ('\n' == ch) {
      lines++;
    }
  }
  lines++;

  sym_tbl = malloc(lines * sizeof(sym_pair_t));
  if (NULL == sym_tbl) {
    fclose(fp);
    return false;
  }
  m_symbol_table = sym_tbl;

  rewind(fp);
  while (!feof(fp)) {
    char s[32];
    if (NULL == fgets(s, sizeof(s), fp)) break;
    sscanf(s, "%08x ", &sym_tbl->address);
    strncpy(sym_tbl->name, &s[9], 16);
    /* strip '\n' */
    sym_tbl->name[strnlen(sym_tbl->name, 16)-1] = '\0';
    sym_tbl++;
    m_symbol_entries++;
  }

  fclose(fp);
  return true;
}

char *elf_get_symbol(uint32_t address)
{
  int ii;
  for (ii = 0; ii<m_symbol_entries; ii++) {
    if (m_symbol_table[ii].address == address) {
      return m_symbol_table[ii].name;
    }
  }
  return "Unknown";
}

void elf_close_file(void)
{
  free(m_symbol_table);
}
